import { StringMap } from './types';
import formData from './formData';
import { session, endSesson } from './index';

let UNAUTHORIZED_HANDLER = null;
export function setUnauthorizedErrorHandler(handler) {
    UNAUTHORIZED_HANDLER = handler;
}

export function get < T >(url: string, data: StringMap): Promise < T > {
    return jhr((xhr: XMLHttpRequest) => {
        xhr.open('GET', `${url}?${formData(data)}`.replace(/\?$/, ''));
        const token = session();
        if (token) {
            xhr.setRequestHeader('token', token);
        }
        xhr.send();
    });
}

export function del < T >(url: string): Promise < T > {
    return jhr((xhr: XMLHttpRequest) => {
        xhr.open('DELETE', url);
        const token = session();
        if (token) {
            xhr.setRequestHeader('token', token);
        }
        xhr.send();
    });
}
export function post < T >(url: string, data: StringMap): Promise < T > {
    return jhr((xhr: XMLHttpRequest) => {
        xhr.open('POST', url);
        const token = session();
        if (token) {
            xhr.setRequestHeader('token', token);
        }
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(formData(data));
    });
}
export function postJson < T >(url: string, data: StringMap): Promise < T > {
    return jhr((xhr: XMLHttpRequest) => {
        xhr.open('POST', url);
        const token = session();
        if (token) {
            xhr.setRequestHeader('token', token);
        }
        xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
        xhr.send(JSON.stringify(data));
    });
}
function jhr < T >(sender: (xhr : XMLHttpRequest) => void): Promise < T > {
    return new Promise((fulfill: (data?: T) => any, reject: (message : any) => any) => {
        const xhr = new XMLHttpRequest();
        xhr.withCredentials = true; // enable authentication server cookies
        xhr.onreadystatechange = () => {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                // if 401 end session and call handler
                if (xhr.status === 401 || xhr.status === 420) {
                    endSesson();
                    if (UNAUTHORIZED_HANDLER) {
                        UNAUTHORIZED_HANDLER();
                    }
                }
                let data: {
                result?: T,
                message?: string
                };
                try {
                    data = (xhr.responseText.length > 1)
                        ? JSON.parse(xhr.responseText)
                        : {};
                } catch (error) {
                    /*eslint-disable*/
                    reject({status: xhr.status, message: ''});
                    /*eslint-disable*/
                }
                if (data && data.result) {
                    fulfill(data.result);
                } else if (data && data.message) {
                    reject({status: xhr.status, message: data.message});
                } else if (xhr.status >= 200 && xhr.status < 400) {
                    fulfill();
                } else {
                    /*eslint-disable*/
                    reject({
                        status: xhr.status,
                        message: xhr.statusText === ''
                            ? '网络连接失败'
                            : xhr.statusText
                    });
                    /*eslint-enable*/
                }
            }
        };
        sender(xhr);
    });
}
